<chapter xml:id="endian.h">
<title><tt>__vic/endian.h</tt></title>

<p>Byte order-related utilities.</p>


<chapter xml:id="endianness">
<title><tt>endianness</tt></title>

<code-block lang="C++">
namespace endian {
enum endianness
{
    unknown = 0,
    little  = 1234,
    big     = 4321,
    pdp     = 3412,
    native  = <nt>&lt;one-of-the-above></nt>
};
} // namespace

using endian::endianness;
</code-block>

<p>Byte order constants. <tt>endian::native</tt> is set equal to one of the
constants and represents the byte order used on the current platform (like
<tt>__BYTE_ORDER__</tt> macro on UNIX-like platforms). The values are supposed
to be used for template specializations or for compile-time checks (e.g. in
<tt>static_assert</tt>).</p>

<section><title>Examples</title>
<code-block lang="C++"><![CDATA[
template<__vic::endianness > struct some_algo; // not implemented

// Implementation for little-endian
template<> struct some_algo<__vic::endian::little>
{
    static void doit() { ... }
};
// Implementation for big-endian
template<> struct some_algo<__vic::endian::big>
{
    static void doit() { ... }
};

// Automatically choose an appropriate implementation for the used platform
some_algo<__vic::endian::native>::doit();
]]></code-block>

<code-block lang="C++">
static_assert(__vic::endian::native == __vic::endian:little,
    "Litte-endian is expected");
</code-block>
</section>

</chapter>


<chapter xml:id="endian--from">
<title><tt>endian::from_...()</tt></title>

<code-block lang="C++"><![CDATA[
template<class T> [[nodiscard]] constexpr T endian::from_little(T v);
template<class T> [[nodiscard]] constexpr T endian::from_big(T v);
]]></code-block>

<p>Return a value represented in native byte order converted from litte/big
endian if appropriate.</p>

<p><tt>T</tt> can be any integral type or enum with size up to
<tt>sizeof(long long)</tt>.</p>

<section><title>Example</title>
<code-block lang="C++"><![CDATA[
uint16_t v;
read_bytes(&v, 2); // serialized as big endian
std::cout << "The value is " << __vic::endian::from_big(v) << '\n';
]]></code-block>
</section>

</chapter>


<chapter xml:id="endian--to">
<title><tt>endian::to_...()</tt></title>

<code-block lang="C++"><![CDATA[
template<class T> [[nodiscard]] constexpr T endian::to_little(T v);
template<class T> [[nodiscard]] constexpr T endian::to_big(T v);
]]></code-block>

<p>Return a value represented in litte/big endian byte order.</p>

<p><tt>T</tt> can be any integral type or enum with size up to
<tt>sizeof(long long)</tt>.</p>

<section><title>Example</title>
<code-block lang="C++"><![CDATA[
uint16_t v = __vic::endian::to_big(...);
write_bytes(&v, 2); // serialize as big endian
]]></code-block>
</section>

</chapter>


<chapter xml:id="swab">
<title><tt>swab16()</tt>, <tt>swab32()</tt>, <tt>swab64()</tt></title>

<code-block lang="C++">
[[nodiscard]] constexpr uint16_t swab16(uint16_t v);
[[nodiscard]] constexpr uint32_t swab32(uint32_t v);
[[nodiscard]] constexpr uint64_t swab64(uint64_t v);
</code-block>

<p>Fast utilities to reverse byte order (usually implemented using
compiler-specific intrinsics).</p>

<section><title>Example</title>
<code-block lang="C++">
static_assert(__vic::swab32(0x01020304) == 0x04030201);
</code-block>
</section>

</chapter>


</chapter>
